package com.traveldream.testing;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

import com.traveldream.entities.Booking;
import com.traveldream.entities.BookingPK;
import com.traveldream.entities.DefaultPacket;
import com.traveldream.entities.Invite;
import com.traveldream.entities.InvitePK;
import com.traveldream.entities.Packet;
import com.traveldream.entities.User;
import com.traveldream.entity_managers.BookingManager;
import com.traveldream.entity_managers.CustomerManager;
import com.traveldream.entity_managers.InviteManager;
import com.traveldream.entity_managers.PacketManager;

@ManagedBean(name="invite_manager_test")
@SessionScoped
public class InviteManagerTest implements TestingTravelDream {
	@EJB
	private InviteManager pm;
	@EJB
	private CustomerManager custm;
	@EJB
	private BookingManager bookm;
	@EJB
	private PacketManager packm;
	
	@ManagedProperty(value="#{test_bean}")
	private TestBean testBean;
	
	private String log;
	private StringBuilder logSb;
	
	@Override
	public void runTests() {	
		logSb=new StringBuilder(300);
		logSb.append("******** TESTING DEL SESSION BEAN: INVITE MANAGER *******");
		logSb.append(System.lineSeparator());
		logSb.append("***** INIZIO TESTING *****");	logSb.append(System.lineSeparator());
		addTest();
		logSb.append(System.lineSeparator());
		findByParametersTest();
		logSb.append(System.lineSeparator());
		inviteAcceptedTest();
		logSb.append(System.lineSeparator());
		this.log=logSb.toString();
		System.out.print(this.log);
		testBean.setProd(false); testBean.setPack(false); testBean.setBook(false);	testBean.setInv(true);
	}

	@Override
	public void addTest() {
		logSb.append("*** ADD TEST INVITE MANAGER ***");logSb.append(System.lineSeparator());
		List<Invite> initialState=pm.findAll();
		logSb.append("> INITIAL STATE: {");
		for( Invite e: initialState )
			logSb.append("   {"+e.getBooking().getUser().getEmail()+","+e.getBooking().getPacket().getId()+","+e.getReceivingEmail()+"}");
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		// 
		if( custm.findAll().size()<2 ) {
			logSb.append("> !!! IMPOSSIBLE RUN THE TEST: ADD AT LEAST 2 CUSTOMERS "); logSb.append(System.lineSeparator());return;
		}
		//
		User u1=custm.findAll().get(0),u2=custm.findAll().get(1);
		Packet p=new Packet();	DefaultPacket dp=new DefaultPacket();	dp.setPacket(p);
		Packet pp=packm.create(p);
		Booking bb=new Booking(); BookingPK bbk=new BookingPK(); bbk.setCustomerEmail(u1.getEmail()); bbk.setPacketId(pp.getId());
		bb.setId(bbk);		bb.setUser(u1);  bb.setPacket(pp);
		bookm.create(bb);
		Invite i=new Invite();	InvitePK ik=new InvitePK();	ik.setCustomerBookedEmail(u1.getEmail()); ik.setBookedPacketId(pp.getId());
		i.setReceivingEmail(u2.getEmail());  i.setBooking(bb); i.setId(ik);
		
		logSb.append("> NEW INVITE CREATED");	logSb.append(System.lineSeparator());
		Invite ii=pm.create(i);
		logSb.append("> NEW INVITE ADDED id = {"+ii.getBooking().getUser().getEmail()+","+ii.getBooking().getPacket().getId()+","+ii.getReceivingEmail()+"}");
		logSb.append(System.lineSeparator());
		List<Invite> finalState=pm.findAll();
		logSb.append("> FINAL STATE: {");
		for( Invite e: finalState )
			logSb.append("   {"+e.getBooking().getUser().getEmail()+","+e.getBooking().getPacket().getId()+","+e.getReceivingEmail()+"}");
		logSb.append("   }");
		logSb.append(System.lineSeparator());		
		initialState.add(ii);
		
		Comparator<Invite> comp=new Comparator<Invite>() {
			public int compare(Invite e1, Invite e2) { 
				if(! e1.getBooking().equals(e2.getBooking() )) {
					if( ! e1.getBooking().getUser().getEmail().equals(e2.getBooking().getUser().getEmail()))
						return e1.getBooking().getUser().getEmail().compareTo(e2.getBooking().getUser().getEmail());
					else
						return e1.getBooking().getPacket().getId()-e2.getBooking().getPacket().getId();
				}
				return e1.getReceivingEmail().compareTo(e2.getReceivingEmail());			
			}
		};
		Collections.sort(initialState,comp);
		Collections.sort(finalState,comp);
		
		if( initialState.equals(finalState) )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY *** ");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END ADD TEST ***");logSb.append(System.lineSeparator());
	}

	@Override
	public void deleteTest() {
		// non � prevista dal sistema la rimozione di inviti
	}

	@Override
	public void addDeleteTest() {
		// non � prevista dal sistema la rimozione di inviti
	}

	@Override
	public void updateTest() {
		// non � prevista dal sistema l'aggiornamento di inviti
	}

	@Override
	public void findByParametersTest() {
		logSb.append("*** FIND TEST INVITE MANAGER ***");logSb.append(System.lineSeparator());
		// view initial state
		List<Invite> initialState=pm.findAll();
		logSb.append("> INITIAL STATE: {");
		for( Invite e: initialState ) {
			InvitePK key=e.getId();
			logSb.append("   { "+key.getCustomerBookedEmail()+","+key.getBookedPacketId()+","+e.getReceivingEmail()+"}");
		}
		logSb.append("   }");
		logSb.append(System.lineSeparator());	
		// create and add new invite
		if( custm.findAll().size()<2 ) {
			logSb.append("> !!! IMPOSSIBLE RUN THE TEST: ADD AT LEAST 2 CUSTOMERS ");logSb.append(System.lineSeparator()); return;
		}
		User u1=custm.findAll().get(0),u2=custm.findAll().get(1);
		Packet p=new Packet();	DefaultPacket dp=new DefaultPacket();	dp.setPacket(p);
		Packet pp=packm.create(p);
		Booking bb=new Booking(); BookingPK bbk=new BookingPK(); bbk.setCustomerEmail(u1.getEmail()); bbk.setPacketId(pp.getId());
		bb.setId(bbk);		bb.setUser(u1);  bb.setPacket(pp);
		bookm.create(bb);
		Invite i=new Invite();	InvitePK ik=new InvitePK();	ik.setCustomerBookedEmail(u1.getEmail()); ik.setBookedPacketId(pp.getId());
		i.setReceivingEmail(u2.getEmail());  i.setBooking(bb); i.setId(ik);
		
		logSb.append("> NEW INVITE CREATED");	logSb.append(System.lineSeparator());
		Invite ii=pm.create(i);
		logSb.append("> NEW INVITE ADDED id = {"+ii.getBooking().getUser().getEmail()+","+ii.getBooking().getPacket().getId()+","+ii.getReceivingEmail()+"}");
		logSb.append(System.lineSeparator());
		
		List<Invite> query=pm.findByReceiver(u2);
		logSb.append("> QUERY EXECUTED find invite for receiver: "+u2.getEmail());logSb.append(System.lineSeparator());
		
		//visualize results
		boolean found=false;
		logSb.append("> QUERY RESULTS: {");
		for( Invite x: query ) {
			if( x.getReceivingEmail().equals(u2.getEmail()) ) {
				found=true;
				logSb.append("   { "+x.getId().getCustomerBookedEmail()+","+x.getId().getBookedPacketId()+","+x.getReceivingEmail()+"}");
			}
		}
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		if( found )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END FIND TEST ***");	logSb.append(System.lineSeparator());
	}
	
	public void inviteAcceptedTest() {
		// si testa l'accettazione di un invito da parte di un utente;
		// la prenotazione deve essere aggiunta && l'invito cancellato
		logSb.append("*** ACCEPTED TEST INVITE MANAGER ***");logSb.append(System.lineSeparator());
		// view initial state
		List<Invite> initialState=pm.findAll();
		logSb.append("> INITIAL STATE: {");
		for( Invite e: initialState ) {
			InvitePK key=e.getId();
			logSb.append("   { "+key.getCustomerBookedEmail()+","+key.getBookedPacketId()+","+e.getReceivingEmail()+"}");
		}
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		// create and add new invite
		if( custm.findAll().size()<2 ) {
			logSb.append("> !!! IMPOSSIBLE RUN THE TEST: ADD AT LEAST 2 CUSTOMERS ");logSb.append(System.lineSeparator()); return;
		}
		User u1=custm.findAll().get(0),u2=custm.findAll().get(1);
		Packet p=new Packet();	DefaultPacket dp=new DefaultPacket();	dp.setPacket(p);
		Packet pp=packm.create(p);
		Booking bb=new Booking(); BookingPK bbk=new BookingPK(); bbk.setCustomerEmail(u1.getEmail()); bbk.setPacketId(pp.getId());
		bb.setId(bbk);		bb.setUser(u1);  bb.setPacket(pp);
		bookm.create(bb);
		Invite i=new Invite();	InvitePK ik=new InvitePK();	ik.setCustomerBookedEmail(u1.getEmail()); ik.setBookedPacketId(pp.getId());
		i.setReceivingEmail(u2.getEmail());  i.setBooking(bb); i.setId(ik);
		
		logSb.append("> NEW INVITE CREATED");	logSb.append(System.lineSeparator());
		Invite ii=pm.create(i);
		logSb.append("> NEW INVITE ADDED id = {"+ii.getBooking().getUser().getEmail()+","+ii.getBooking().getPacket().getId()+","+ii.getReceivingEmail()+"}");
		logSb.append(System.lineSeparator());
		
		pm.acceptInvite(i, u2);
		logSb.append("> INVITE ACCEPTED ");logSb.append(System.lineSeparator());
		logSb.append("> BOOKINGS  {   ");
		boolean trovatoBooking=false;
		for( Booking b: bookm.findByCustomer(u2) ) 
			if( b.getPacket().getId()==ii.getId().getBookedPacketId() ) {
				trovatoBooking=true;
				BookingPK key=b.getId();
				logSb.append("   { "+key.getCustomerEmail()+","+key.getPacketId()+" }");
			}
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		logSb.append("> INVITES  {   ");
		boolean trovatoInvite=false;
		for( Invite b: pm.findByReceiver(u2) ) 
			if( b.equals(ii) ) {
				trovatoInvite=true; 
				InvitePK key=b.getId();
				logSb.append("   { "+key.getCustomerBookedEmail()+","+key.getBookedPacketId()+","+b.getReceivingEmail()+"}");	
			}
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		if( trovatoBooking && !trovatoInvite ) 
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END ACCEPT-INVITE TEST ***");	logSb.append(System.lineSeparator());		
	}

	public TestBean getTestBean() {
		return testBean;
	}

	public void setTestBean(TestBean testBean) {
		this.testBean = testBean;
	}

	public String getLog() {
		return log;
	}

	public void setLog(String log) {
		this.log = log;
	}
	
}
